home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 25 / AMIGAplus Sonderheft 25 (2000)(Falke)(DE)(Track 1 of 4)[!].iso / PublicDomain / Anwendungen / AmigaEYE_V39.7 / ScreenNotifly.lha / ScreenNotify / src / patch.c < prev    next >
C/C++ Source or Header  |  1995-03-26  |  11KB  |  335 lines

  1. /*
  2.  * patch.c V1.0
  3.  *
  4.  * Patch routines
  5.  *
  6.  * (c) 1995 Stefan Becker
  7.  */
  8.  
  9. #include "screennotify.h"
  10.  
  11. /* Local data */
  12. static ULONG (*OldCloseScreen)(__A0 struct Screen *, __A6 struct Library *);
  13. static LONG  (*OldCloseWB)(__A6 struct Library *);
  14. static ULONG (*OldOpenWB)(__A6 struct Library *);
  15. static ULONG (*OldPubScreenStatus)(__A0 struct Screen *, __D0 ULONG,
  16.                                    __A6 struct Library *);
  17.  
  18. /* Local defines */
  19. #define OFFSET_CloseScreen     -0x042
  20. #define OFFSET_CloseWorkBench  -0x04E
  21. #define OFFSET_OpenWorkBench   -0x0D2
  22. #define OFFSET_PubScreenStatus -0x228
  23.  
  24. /* Patch for CloseScreen() */
  25. __geta4 static ULONG PatchCloseScreen(__A0 struct Screen *s,
  26.                                       __A6 struct Library *IntuitionBase)
  27. {
  28.  BYTE sigbit;
  29.  
  30.  DEBUGLOG(kprintf("PatchCloseScreen: Screen 0x%08lx\n", s);)
  31.  
  32.  /* Allocate signal bit */
  33.  if ((sigbit = AllocSignal(-1)) != -1) {
  34.   struct ClientListData         *cld  = &ScreenNotifyBase->snb_CloseScreenClients;
  35.   struct MsgPort                *rp   = &cld->cld_MsgPort;
  36.   struct ScreenNotifyMessage    *snm  = &cld->cld_Message;
  37.   struct CloseScreenClientNode  *cscn;
  38.  
  39.   DEBUGLOG(kprintf("PatchCloseScreen: Signalbit %ld\n", sigbit);)
  40.  
  41.   /* Obtain semaphore for CloseScreen client list data */
  42.   ObtainSemaphore(&cld->cld_Semaphore);
  43.  
  44.   DEBUGLOG(kprintf("PatchCloseScreen: Semaphore locked.\n");)
  45.  
  46.   /* Initialize message port */
  47.   rp->mp_SigBit  = sigbit;
  48.   rp->mp_SigTask = FindTask(NULL);
  49.  
  50.   /* Initialize message */
  51.   snm->snm_Type  = SCREENNOTIFY_TYPE_CLOSESCREEN;
  52.   snm->snm_Value = s;
  53.  
  54.   /* Get head of CloseScreen client list */
  55.   cscn = (struct CloseScreenClientNode *) GetHead(&cld->cld_List);
  56.  
  57.   /* Traverse list */
  58.   while (cscn) {
  59.  
  60.    /* Do the screen pointer values match? NULL matches any screen! */
  61.    if ((cscn->cscn_Screen == NULL) || (cscn->cscn_Screen == s)) {
  62.     struct MsgPort *mp = (struct MsgPort *) cscn->cscn_Node.ln_Name;
  63.  
  64.     /* Make sure that we don't send a message to our caller task! */
  65.     if (rp->mp_SigTask != mp->mp_SigTask) {
  66.  
  67.      DEBUGLOG(kprintf("PatchCloseScreen: Sending to 0x%08lx\n", mp);)
  68.  
  69.      /* Send message to client */
  70.      PutMsg(mp, (struct Message *) snm);
  71.  
  72.      /* Wait for reply */
  73.      WaitPort(rp);
  74.  
  75.      DEBUGLOG(kprintf("PatchCloseScreen: Reply from 0x%08lx\n", mp);)
  76.  
  77.      /* Retrieve message */
  78.      GetMsg(rp);
  79.     }
  80.    }
  81.  
  82.    /* Get next entry */
  83.    cscn = (struct CloseScreenClientNode *) GetSucc((struct Node *) cscn);
  84.   }
  85.  
  86.   DEBUGLOG(kprintf("PatchCloseScreen: Messages sent.\n");)
  87.  
  88.   /* Release semaphore */
  89.   ReleaseSemaphore(&cld->cld_Semaphore);
  90.  
  91.   DEBUGLOG(kprintf("PatchCloseScreen: Semaphore released.\n");)
  92.  
  93.   /* Free signal bit */
  94.   FreeSignal(sigbit);
  95.  }
  96.  
  97.  DEBUGLOG(kprintf("PatchCloseScreen: Calling original function.\n");)
  98.  
  99.  /* Return value from original function */
  100.  return(OldCloseScreen(s, IntuitionBase));
  101. }
  102.  
  103. /* Inform clients */
  104. static void InformClients(struct ClientListData *cld, ULONG type, APTR value)
  105. {
  106.  BYTE sigbit;
  107.  
  108.  DEBUGLOG(kprintf("InformClients(%ld): Value 0x%08lx\n", type, value);)
  109.  
  110.  /* Allocate signal bit */
  111.  if ((sigbit = AllocSignal(-1)) != -1) {
  112.   struct MsgPort             *rp  = &cld->cld_MsgPort;
  113.   struct ScreenNotifyMessage *snm = &cld->cld_Message;
  114.   struct Node                *n;
  115.  
  116.   DEBUGLOG(kprintf("InformClients(%ld): Signalbit %ld\n", type, sigbit);)
  117.  
  118.   /* Obtain semaphore for client list data */
  119.   ObtainSemaphore(&cld->cld_Semaphore);
  120.  
  121.   DEBUGLOG(kprintf("InformClients(%ld): Semaphore locked.\n", type);)
  122.  
  123.   /* Initialize message port */
  124.   rp->mp_SigBit  = sigbit;
  125.   rp->mp_SigTask = FindTask(NULL);
  126.  
  127.   /* Initialize message */
  128.   snm->snm_Type  = type;
  129.   snm->snm_Value = value;
  130.  
  131.   /* Get head of client list */
  132.   n = GetHead(&cld->cld_List);
  133.  
  134.   /* Traverse list */
  135.   while (n) {
  136.    struct MsgPort *mp = (struct MsgPort *) n->ln_Name;
  137.  
  138.    /* Make sure that we don't send a message to our caller task! */
  139.    if (rp->mp_SigTask != mp->mp_SigTask) {
  140.  
  141.     DEBUGLOG(kprintf("InformClients(%ld): Sending to 0x%08lx\n", type, mp);)
  142.  
  143.     /* Send message to client */
  144.     PutMsg(mp, (struct Message *) snm);
  145.  
  146.     /* Wait for reply */
  147.     WaitPort(rp);
  148.  
  149.     DEBUGLOG(kprintf("InformClients(%ld): Reply from 0x%08lx\n", type, mp);)
  150.  
  151.     /* Retrieve message */
  152.     GetMsg(rp);
  153.    }
  154.  
  155.    /* Get next entry */
  156.    n = GetSucc(n);
  157.   }
  158.  
  159.   DEBUGLOG(kprintf("InformClients(%ld): Messages sent.\n", type);)
  160.  
  161.   /* Release semaphore */
  162.   ReleaseSemaphore(&cld->cld_Semaphore);
  163.  
  164.   DEBUGLOG(kprintf("InformClients(%ld): Semaphore released.\n", type);)
  165.  
  166.   /* Free signal bit */
  167.   FreeSignal(sigbit);
  168.  }
  169. }
  170.  
  171. /* Patch for PubScreenStatus() */
  172. __geta4 static ULONG PatchPubScreenStatus(__A0 struct Screen *s, __D0 ULONG flags,
  173.                                           __A6 struct Library *IntuitionBase)
  174. {
  175.  struct PubScreenNode *psn = NULL;
  176.  ULONG rc;
  177.  
  178.  DEBUGLOG(kprintf("PatchPubScreenStatus: Screen 0x%08lx, Flags 0x%04lx\n", s, flags);)
  179.  
  180.  /* Find PubScreenNode for screen */
  181.  {
  182.   struct List *l;
  183.  
  184.   DEBUGLOG(kprintf("PatchPubScreenStatus: Locking PubScreenList.\n");)
  185.  
  186.   /* Lock public screen list */
  187.   if (l = LockPubScreenList()) {
  188.  
  189.    /* Get head of list */
  190.    psn = (struct PubScreenNode *) GetHead(l);
  191.  
  192.    /* Traverse list */
  193.    while (psn && (psn->psn_Screen != s))
  194.     psn = (struct PubScreenNode *) GetSucc((struct Node *) psn);
  195.  
  196.    DEBUGLOG(kprintf("PatchPubScreenStatus: Unlocking PubScreenList.\n");)
  197.  
  198.    /* Unlock list */
  199.    UnlockPubScreenList();
  200.   }
  201.  }
  202.  
  203.  DEBUGLOG(kprintf("PatchPubScreenStatus: PubScreenNode 0x%08lx\n", psn);)
  204.  
  205.  /* PubScreenNode valid and "Private" event? */
  206.  if (psn && ((flags & PSNF_PRIVATE) == PSNF_PRIVATE))
  207.  
  208.   /* Yes, send message to clients */
  209.   InformClients(&ScreenNotifyBase->snb_PubScreenClients,
  210.                 SCREENNOTIFY_TYPE_PRIVATESCREEN, psn);
  211.  
  212.  DEBUGLOG(kprintf("PatchPubScreenStatus: Calling original function.\n");)
  213.  
  214.  /* Call original function */
  215.  rc = OldPubScreenStatus(s, flags, IntuitionBase);
  216.  
  217.  DEBUGLOG(kprintf("PatchPubScreenStatus: Original function returned 0x%04lx\n", rc);)
  218.  
  219.  /* PubScreenNode valid & successful "Public" event or unsuccessful "Private" event? */
  220.  if (psn &&
  221.      ((((flags & PSNF_PRIVATE) == 0) &&            ((rc & 0x1) == 0x1)) ||
  222.       (((flags & PSNF_PRIVATE) == PSNF_PRIVATE) && ((rc & 0x1) == 0x0))))
  223.  
  224.   /* Yes, inform clients */
  225.   InformClients(&ScreenNotifyBase->snb_PubScreenClients,
  226.                 SCREENNOTIFY_TYPE_PUBLICSCREEN, psn);
  227.  
  228.  /* Return value from original function */
  229.  return(rc);
  230. }
  231.  
  232. /* Patch for CloseWorkBench() */
  233. __geta4 static LONG PatchCloseWB(__A6 struct Library *IntuitionBase)
  234. {
  235.  ULONG rc;
  236.  
  237.  DEBUGLOG(kprintf("PatchCloseWB\n");)
  238.  
  239.  /* Inform WB clients that the Workbench will be closed */
  240.  InformClients(&ScreenNotifyBase->snb_WorkbenchClients, SCREENNOTIFY_TYPE_WORKBENCH,
  241.                (APTR) FALSE);
  242.  
  243.  DEBUGLOG(kprintf("PatchCloseWB: Calling original function.\n");)
  244.  
  245.  /* Call old function */
  246.  if (!(rc = OldCloseWB(IntuitionBase)))
  247.  
  248.   /* Inform WB clients that the Workbench has NOT been closed! */
  249.   InformClients(&ScreenNotifyBase->snb_WorkbenchClients, SCREENNOTIFY_TYPE_WORKBENCH,
  250.                 (APTR) TRUE);
  251.  
  252.  DEBUGLOG(kprintf("PatchCloseWB: Original function returned %ld\n", rc);)
  253.  
  254.  /* Return value from original function */
  255.  return(rc);
  256. }
  257.  
  258. /* Patch for OpenWorkBench() */
  259. __geta4 static ULONG PatchOpenWB(__A6 struct Library *IntuitionBase)
  260. {
  261.  ULONG rc;
  262.  
  263.  DEBUGLOG(kprintf("PatchOpenWB: Calling original function.\n");)
  264.  
  265.  /* Call old function first */
  266.  if (rc = OldOpenWB(IntuitionBase))
  267.  
  268.   /* Inform WB clients that the Workbench has been opened */
  269.   InformClients(&ScreenNotifyBase->snb_WorkbenchClients, SCREENNOTIFY_TYPE_WORKBENCH,
  270.                 (APTR) TRUE);
  271.  
  272.  DEBUGLOG(kprintf("PatchOpenWB: Original function returned %ld\n", rc);)
  273.  
  274.  /* Return value from original function */
  275.  return(rc);
  276. }
  277.  
  278. /* Patch functions in intuition.library. Called in Forbid() state */
  279. void PatchFunctions(struct Library *ib)
  280. {
  281.  /* Patch intuition.library */
  282.  OldCloseScreen     = SetFunction(ib, OFFSET_CloseScreen,     (APTR) PatchCloseScreen);
  283.  OldCloseWB         = SetFunction(ib, OFFSET_CloseWorkBench,  (APTR) PatchCloseWB);
  284.  OldOpenWB          = SetFunction(ib, OFFSET_OpenWorkBench,   (APTR) Patc